# preshrunk-cotton
# Copyright (C) 2010, 2011 Approximatrix, LLC
# http://code.google.com/p/preshrunk-cotton/
# http://approximatrix.com/
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
# A full version of the license terms is available in LICENSE.

import os.path
import os

class TOCNode:
    """A single node in the table of contents.  The name should consist of the
    local name of the file or directory.  The children array should only contain
    information if the node is a directory."""
    def __init__(self,name='',depth=0,parent=None):
        self.name = name
        self.children = []
        self.depth = depth
        self.parent = parent
        
    def isdir(self):
        return (len(self.children) > 0)
        
    def path(self):
        if self.parent:
            return os.path.join(self.parent.path(),self.name)
        else:
            return self.name
        
class SimpleTOC:
    """A class for handling a table of contents based on a textile-like
    file describing said table.  The files and directories should be
    called out simply by name.  Files may include extensions."""
    def __init__(self,filename):
        self.root = TOCNode()
        self.file = filename

    def parse_line(self, line):
        line = line.strip()
        sline = line.split(' ',1)
        return sline[0].count('*'), sline[1]
                
    def process(self):
        fp = open(self.file, 'r')
        current = self.root
        for line in fp:
            depth,entry = self.parse_line(line)
            if depth == 0:
                raise ValueError('An entry depth of zero is not allowed')
            
            # Move to the last child if we have a greater depth
            if depth > current.depth+1:
                current = current.children[-1]
            # Move to the parent if we have a peer
            elif depth == current.depth:
                current = current.parent

            # Format the entry
            #if entry.endswith('.textile'):
            #    entry = entry.replace('.textile','.html')
                
            #if not entry.endswith('.html'):
            #    entry = entry+'.html'
            
            # Add a child
            if depth == current.depth+1:
                current.children.append(TOCNode(entry,depth,current))
            
        # If we're done, close up
        fp.close()
        
class DefaultTOC:
    """A default table of contents class for handling a simple scan of the
    file system."""
    def __init__(self,directory):
        self.startdir = directory
        self.root = TOCNode(directory)
    
    def find_parent(self,dirnodes,path):
        for node in dirnodes:
            if node.path() == path:
                return node
        return self.root
    
    def process(self):
        
        dirnodes = []
        dirnodes.append(self.root)
        for root, dirs, files in os.walk(self.startdir):
            
            parent = self.find_parent(dirnodes,root)
            
            for entry in dirs:
                if entry == 'CVS' or entry.startswith('.'):
                    continue
                parent.children.append(TOCNode(entry,parent.depth+1,parent))
                dirnodes.append(parent.children[-1])
            
            for entry in files:
                if entry.lower().endswith('.html'):
                    parent.children.append(TOCNode(entry,parent.depth+1,parent))
                
        
